package cn.biplam.common.wrapper;

import java.io.Serializable;
import java.util.ArrayList;

/**
 * 	行数未知，列数已知的2维表
 * @author XiaoRuxing
 * @create12:33:31 PM
 * @version 1.0
 */
public class D2Array<M> implements Serializable{
	private static final long serialVersionUID = 4069513804877401685L;//类序列号
	private ArrayList<M []> aTable; //存储2维数据的容器
	private int iRowNumber;//行数
	private int iColNumber;//列数

	/**
	 * @param iColNumber 列数
	 */
	public D2Array(int iColNumber){
		aTable=new ArrayList<M[]>();
		this.iRowNumber=0;         //初始化行数
		this.iColNumber=iColNumber;	//初始化列数
	}

	/**
	 * 	在表尾插入一行
	 * @param mValue 行数组
	 */
	public void put(M[] mValue){
		aTable.add(mValue);
		iRowNumber++;
	}

	/**
	 * 在指定位置，插入一行，指定位置后的所有行往后移动一行，然后插入
	 * @param iRowIndex 行
	 * @param mValue	数组
	 * @throws 如果指定的行下标超过了现有的行数或者数组长度不等于列数返回越界异常
	 */
	public void put(int iRowIndex,M[] mValue) throws ErrorMessage{

		/** 判断行是否越界 */
		rowRangeCheck(iRowIndex-1);

		/** 判断列是否越界 */
		colNumEqualCheck(mValue);

		aTable.add(iRowIndex, mValue);

		/** 更新行计算器 */
		iRowNumber++;
	}

	/**
	 * 在末尾插入一个2维表
	 * @param d2aCopy
	 * @throws ErrorMessage 
	 */
	public void put(D2Array<? extends M> d2a) throws ErrorMessage{
		for(int i=0;i<d2a.getRowNumber();i++){
			put(d2a.get(i));
		}
	}

	/**
	 * 修改指定行
	 * @param iRowIndex 行
	 * @param mValue	数组
	 * @throws 如果指定的行下标超过了现有的行数或者数组长度不等于列数返回越界异常
	 */
	public void set(int iRowIndex,M[] mValue) throws ErrorMessage{

		/** 判断行是否越界 */
		rowRangeCheck(iRowIndex);

		/** 判断列是否越界 */
		colNumEqualCheck(mValue);

		aTable.set(iRowIndex, mValue);
	}

	/**
	 * 修改指定单元格的值
	 * @param iRowIndex 行
	 * @param iColIndex	列
	 * @param mValue	值
	 * @throws ErrorMessage 
	 * @throws 如果指定的行下标超过了现有的行数或者列数返回越界异常
	 */
	public void set(int iRowIndex,int iColIndex,M mValue) throws ErrorMessage{

		/** 判断下标是否越界 */
		rowRangeCheck(iRowIndex);
		colRangeCheck(iColIndex);

		M [] ma=aTable.get(iRowIndex);
		ma[iColIndex]=mValue;
		aTable.set(iRowIndex, ma);
	}

	/**
	 * 返回指定行
	 * @param iRowIndex	行
	 * @return	行数组
	 * @throws ErrorMessage 
	 * @throws 如果指定的行下标超过了现有的行数返回越界异常
	 */
	public M[] get(int iRowIndex) throws ErrorMessage{
		rowRangeCheck(iRowIndex);
		return aTable.get(iRowIndex);
	}

	/**
	 * 返回指定单元格的值
	 * @param iRowIndex	行
	 * @param iColIndex	列
	 * @return	指定单元格的值
	 * @throws ErrorMessage 
	 * @throws 如果指定的行下标超过了现有的行数或者列数返回越界异常
	 */
	public M get(int iRowIndex,int iColIndex) throws ErrorMessage{
		rowRangeCheck(iRowIndex);
		colRangeCheck(iColIndex);
		return aTable.get(iRowIndex)[iColIndex];
	}

	/**
	 * 返回行数
	 * @return 行数
	 */
	public int getRowNumber(){
		return this.iRowNumber;
	}

	/**
	 * 返回列数
	 * @return	列数
	 */
	public int getColNumber(){
		return this.iColNumber;
	}

	/**
	 * 返回是否为空
	 * @return	是否为空
	 */
	public boolean isEmpty(){
		return iRowNumber==0;
	}

	/**
	 * 	删除指定行 
	 * @param iRowIndex 行
	 * @throws ErrorMessage 
	 * @throws 如果指定的行下标超过了现有的行数返回越界异常
	 */
	public void remove(int iRowIndex) throws ErrorMessage{
		rowRangeCheck(iRowIndex);
		aTable.remove(iRowIndex);
		iRowNumber--;
	}

	/**
	 * 判断列下标是否越界
	 * @param iColIndex	列号
	 */
	private void colRangeCheck(int iColIndex) throws ErrorMessage{
		if (iColIndex >= iColNumber || iColIndex < 0){
			throw new ErrorMessage("下标越界");
		}
	}

	/**
	 * 判断行下标是否越界
	 * @param iRowIndex	行号
	 * @throws ErrorMessage 
	 */
	private void rowRangeCheck(int iRowIndex) throws ErrorMessage{
		if (iRowIndex >= iRowNumber || iRowIndex < 0){
			throw new ErrorMessage("下标越界");
		}
	}

	/**
	 * 判断数组列数是否与D2Array列数相等
	 * @param iLength
	 * @throws ErrorMessage
	 */
	private void colNumEqualCheck(M[] mValue) throws ErrorMessage{

		int iLength=mValue.length;
		if (iLength != iColNumber){
			throw new ErrorMessage("下标越界:"+" 实际列数="+iLength+" 最大列数"+iColNumber+" !");
		}
	}

	/**
	 * 返回字符串表示形式
	 * @return
	 */
	public String toString(){

		/** 结果字符串 */
		StringBuilder sp=new StringBuilder();

		try {
			for(int i=0;i<iRowNumber;i++){
				getColString(sp,get(i));
				sp.append("\n");
			}
		} catch (ErrorMessage e) {
			return e.toString();
		}
		return sp.toString();
	}
	
	/**
	 * 一行的字符串表示形式
	 * @param sp
	 * @param mCol
	 */
	private void getColString(StringBuilder sp,M[] mCol){
		String sCol=null;
		for(int j=0;j<mCol.length;j++){
			if(mCol[j]==null){
				sCol="";
			}else{
				sCol=mCol[j].toString();
			}
			sp.append(sCol);
			/** 判断是否是最后一行 */
			if(j<mCol.length-1){
				sp.append(",");
			}
		}
	}
}
